/*
 *  cpu_parse_display/cpu_display.c
 *  
 *              CPU Monitor 
 *
 *    Spring Semester.  044800.    Technion.
 *   Copyright (C) 2006  Evgeny Shulman  and Elizabeth Shtrom 
 */

#include "../cpu_consts.h"
#include "../cpu_common.h"
#include "cpu_display.h"
#include "cpu_parse.h"


#ifdef __KERNEL__

#include <linux/memory.h>
#include <linux/string.h>
#include <linux/errno.h>

#else
     /* This one for user space */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

#endif


int print_Xgt      (parsed_Xgt_s  * );

int print_seg_desc (parsed_desc_s *s);
int print_desc(parsed_desc_s *s);

int print_regs      (parsed_regs_s  *s);

int print_page ( parsed_page_s *s);


//static char *set_eflags[] = {
//	"carry", NULL, "parity",  NULL, "adjust",  NULL, "zero", "sign",
//	"trace", "intr-on", "dir", "overflow",  NULL, NULL, "nestedtask", NULL,
//	"resume", "vm", "align", "vif", "vip", "id", NULL, NULL,
//	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};	
//	
//	

#ifdef __KERNEL__ 	
	int display_tss(struct tss_struct  *t)
#else	
	int display_tss(cm_tss_struct *t)
#endif
{
	
	PDEBUG_DISP("\n---------------TSS-----------------------\n");
	PDEBUG_DISP("    cs = %04x,  eip = 0x%8.8lx\n", t->es, t->eip);
	PDEBUG_DISP("    ss = %04x,  esp = 0x%8.8lx\n", t->ss, t->esp);
	PDEBUG_DISP("   ss0 = %04x, esp0 = 0x%8.8lx\n", t->ss0, t->esp0);
	PDEBUG_DISP("   ss1 = %04x, esp1 = 0x%8.8lx\n", t->ss1, t->esp1);
	PDEBUG_DISP("   ss2 = %04x, esp2 = 0x%8.8lx\n", t->ss2, t->esp2);
	PDEBUG_DISP("   ldt = %04x,  cr3 = 0x%8.8lx\n", t->ldt, t->__cr3);
	PDEBUG_DISP("    ds = %04x,  es  = %04x\n",     t->ds, t->es);
	PDEBUG_DISP("    fs = %04x   gs =  %04x\n",     t->fs, t->gs);
	
	
	PDEBUG_DISP("   eax = 0x%8.8lx, ebx = 0x%8.8lx ecx = 0x%8.8lx edx = 0x%8.8lx\n",
			t->eax, t->ebx, t->ecx, t->edx);
	PDEBUG_DISP("   esi = 0x%8.8lx, edi = 0x%8.8lx ebp = 0x%8.8lx\n",
			t->esi, t->edi, t->ebp);
	PDEBUG_DISP("\n-----------------------------------------\n");
			return 0;
}


int display_regs      (regs_s  *r){
	parsed_regs_s out;
	parse_regs ( r, &out) ;
	print_regs (&out ) ;
	return 0;
	
}

	
int print_regs      (parsed_regs_s  *s){

 
	PDEBUG_DISP("\n---------------REGS----------------------\n");
	PDEBUG_DISP("cr0=%s     ", s->cr0) ;  PDEBUG_DISP("cr3=%s\n", s->cr3);
	PDEBUG_DISP("cr2=%s     ", s->cr2);   PDEBUG_DISP("cr4=%s\n", s->cr4);
	PDEBUG_DISP("\n");
	PDEBUG_DISP("dr0=%s     ", s->dr0); PDEBUG_DISP("dr4=%s\n", s->dr4);
	PDEBUG_DISP("dr1=%s     ", s->dr1); PDEBUG_DISP("dr5=%s\n", s->dr5);	
	PDEBUG_DISP("dr2=%s     ", s->dr2); PDEBUG_DISP("dr6=%s\n", s->dr6);
	PDEBUG_DISP("dr3=%s     ", s->dr3); PDEBUG_DISP("dr7=%s\n", s->dr7);
	PDEBUG_DISP("\n");
	
	PDEBUG_DISP("cs=%s           ", s->cs); PDEBUG_DISP("ldtr=%s\n", s->ldtr);   
	PDEBUG_DISP("ss=%s           ", s->ss); PDEBUG_DISP("tr=%s\n", s->tr);       
	PDEBUG_DISP("es=%s\n", s->es);
	PDEBUG_DISP("ds=%s\n", s->ds);	
	PDEBUG_DISP("fs=%s\n", s->fs);
	PDEBUG_DISP("gs=%s\n", s->gs);
	
	PDEBUG_DISP("\ngdtr:\n");
	print_Xgt ( &(s->gdtr)) ;
	
	PDEBUG_DISP("idtr:\n");
	print_Xgt ( &(s->idtr) );
	PDEBUG_DISP("\n-----------------------------------------\n");
	
	return 0 ;
}	




int display_idt      (cm_gate_desc_t *idt, int vec,  int count ){
	
	parsed_desc_s out[IDT_ENTRIES]; 
	
	if ( ! CHECK_INDEX(vec, IDT_ENTRIES) ) 	 return -INDEX_INVALID;
	FIX_COUNTER( vec, count, IDT_ENTRIES, IDT_ENTRIES);
	
	parse_idt(idt, out,  vec,	 count  ) ;
	
	PDEBUG_DISP("\n---------------IDT-----------------------\n");
	while (count--) {
		print_desc ( out + vec ) ;
		vec++;
	}
	PDEBUG_DISP("\n-----------------------------------------\n");
	
	return 0;
}

int display_idt_stats(im_irq_stat_s *im_irq_stat_data){
	int i ;
	for (  i =  0 ; i <IDT_ENTRIES ; i ++){
		if ( im_irq_stat_data->irqs[i] ) 
			PDEBUG_DISP(" %d   -> %d ", i, im_irq_stat_data->irqs[i]) ;
	} 
	return 0;
}


int display_gdt      (cm_desc_t *gdt, int sel,	int count)
{
	parsed_desc_s out[GDT_ENTRIES]; 
	
	if ( ! CHECK_INDEX(sel, GDT_ENTRIES) ) 	 return -INDEX_INVALID;
	FIX_COUNTER( sel, count, GDT_ENTRIES, GDT_ENTRIES);
	
	parse_gdt(gdt, out,  sel,	 count  ) ;
	PDEBUG_DISP("\n---------------GDT----------------------\n");
	
	while (count--) {
		print_desc ( out+sel );
		sel++;
	}
	PDEBUG_DISP("\n-----------------------------------------\n");
	
	return 0;
}
	
	
	
	
int display_ldt  (cm_desc_t *ldt, int sel,	int count  ) {
	
	parsed_desc_s out[LDT_ENTRIES]; 
	
	if ( ! CHECK_INDEX(sel, LDT_ENTRIES) ) 	 return -INDEX_INVALID;
	FIX_COUNTER( sel, count, LDT_ENTRIES, LDT_ENTRIES);
	
	parse_ldt(ldt, out,  sel,	 count  ) ;
	
	PDEBUG_DISP("----------------LDT--------------------\n");
	while (count--) {
		print_desc ( out+sel );
		sel++;
	}
	PDEBUG_DISP("\n-----------------------------------------\n");
	
	return 0;

}



	
	
int print_desc(parsed_desc_s *s){
	//TODO !! PARSE GATE _ SEG 
	

	if ( *(s->index )!= '\0'  )  PDEBUG_DISP("%s ",s->index );
	if ( *(s->entry )!= '\0'  ) PDEBUG_DISP("raw content: %s ",s->entry );
	if ( *(s->status )!= '\0'  ) PDEBUG_DISP("%s ",s->status );
	if ( *(s->type )!= '\0'  )PDEBUG_DISP("type=%s ",s->type );
	if ( *(s->base )!= '\0'  )PDEBUG_DISP("base=%s ",s->base );
	if ( *(s->limit )!= '\0' )PDEBUG_DISP("limit=%s ",s->limit );
	if ( *(s->dpl )!= '\0'   )PDEBUG_DISP("dpl=%s ",s->dpl );
	if ( *(s->sel )!= '\0'    )PDEBUG_DISP("sel=%s ",s->sel  );
	if ( *(s->off )!= '\0' )PDEBUG_DISP("offset = %s "   ,s->off );
	PDEBUG_DISP("\n");
	
	return 0;
}


int print_seg_desc(parsed_desc_s *s)
{
	if ( *(s->entry )!= '\0'  ) PDEBUG_DISP("raw content: %s ",s->entry );
	if ( *(s->type )!= '\0'  ) PDEBUG_DISP("%s ",s->type );
	if ( *(s->base )!= '\0'  )PDEBUG_DISP("base=%s ",s->base );
	if ( *(s->limit )!= '\0' )PDEBUG_DISP("limit=%s ",s->limit );
	if ( *(s->dpl )!= '\0'   )PDEBUG_DISP("dpl=%s ",s->dpl );
	if ( *(s->mode )!= '\0'  )PDEBUG_DISP("mode=%s ",s->mode );
	if ( *(s->db )!= '\0'    )PDEBUG_DISP("db=%s ",s->db  );
	if ( *(s->type_1 )!= '\0' )PDEBUG_DISP("%s "   ,s->type_1 );
	if ( *(s->type_2 )!= '\0' )PDEBUG_DISP("%s "   ,s->type_2 );
	
	
	PDEBUG_DISP("\n");
	return 0;
}



//void display_eflags(unsigned long ef)
//{
//	int i, iopl;
//	PDEBUG_DISP("eflags = 0x%08lx ", ef);
//	for (i = 0; i < 22; i++) {
//		if (test_bit(i, &ef) && set_eflags[i])
//			PDEBUG_DISP("%s ", set_eflags[i]);
//}


int display_Xgt( struct Xgt_desc_struct *r){
	parsed_Xgt_s out;
	
	parse_Xgt  (r, &out);
	print_Xgt (&out);
	return 0;
}

int print_Xgt      (parsed_Xgt_s  *out ){
	PDEBUG_DISP("\tadress=%s \n",   out->address);
	PDEBUG_DISP("\tsize  =%s \n",   out->size);
	return 0;
}


int display_pgdir( void * pgdir, int index , int count )
{
	int i;
	parsed_page_s out[PGD_TABLE_ENTRIES]; 
	if ( ! CHECK_INDEX(index, PGD_TABLE_ENTRIES) ) 	 return -INDEX_INVALID;
	FIX_COUNTER( index, count, PGD_TABLE_ENTRIES, PGD_TABLE_ENTRIES);
	
	PDEBUG_DISP(" page directory: from %d to %d:\n", index, index+count);
	parse_pgdir(  pgdir, out,  index , count );
	
	for (i = 0; i < count; i++) {
		print_page ( out + index + i );   	
	}
	return 0;
} 

int display_ptable( void * ptable , int index , int count )
{
	int i;
	parsed_page_s out[PT_TABLE_ENTRIES]; 
	
	if ( ! CHECK_INDEX(index, PT_TABLE_ENTRIES) ) 	 return -INDEX_INVALID;
	FIX_COUNTER( index, count, PT_TABLE_ENTRIES, PT_TABLE_ENTRIES);
	
 	PDEBUG_DISP(" page table: from %d to %d:\n", index, index+count);
 	parse_ptable(  ptable, out,  index , count );
 	for (i = 0; i < count; i++) {
		print_page ( out + index + i );
	}
 return 0;
}


int print_page ( parsed_page_s *s){
	PDEBUG_DISP("%s : %s : %s : %s : %s %s %s %s %s %s %s %s %s %s\n",
	  s->index   ,
	  s->entry   ,
	  s->status  ,
	  s->frame   ,
	  s->user    ,
	  s->mode    ,
	  s->status  ,
	  s->dirty   ,
	  s->sel     ,
	  s->off     ,
	  s->global  ,
	  s->pse     ,
	  s->pwt     ,
	  s->pcd     );
	 

	return 0;                                           
	                                                    
}	                                                    
                                                        
                                                        
                                                        
                                                        
                                                        
                                                        
                                                        
                                                        
                                                        
